package com.heima.filter;

import cn.hutool.core.text.AntPathMatcher;
import cn.hutool.core.util.StrUtil;
import com.heima.config.AuthProperties;
import com.heima.utils.JwtTool;
import lombok.RequiredArgsConstructor;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;

@Component
@RequiredArgsConstructor
public class LoginGlobalFilter implements GlobalFilter, Ordered {

    private final AuthProperties authProperties;
    // 路径匹配，支持通配符
    private final AntPathMatcher antPathMatcher =new AntPathMatcher();

    private final JwtTool jwtTool;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取用户请求的上下文对象 Request()[请求的任何数据都可以通过它获取] Response()[可以响应数据]
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        // 1. 获取用户请求地址
        String path = request.getURI().getPath();
        // 2.判断当前请求是否需要被拦截
        if(isAllowPath(path)){
            // 无需拦截，放行
            return chain.filter(exchange);
        }
        // 3、获取用户传入的令牌 authorization
        String token = request.getHeaders().getFirst("authorization");
        Long userId = null;
        if (StrUtil.isEmpty(token) ||
                // 解析令牌,解析失败，拦截处理
                (userId = jwtTool.parseToken(token))==null) {
            // 提示参数错误
            response.setStatusCode(HttpStatus.FORBIDDEN); // 响应状态码
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON); // 响应JSON类型
            // 响应数据
            return response.writeWith(Mono.just(response.bufferFactory().wrap("{\"msg\":\"请先登录！\"}".getBytes(StandardCharsets.UTF_8))));
        }
        // 解析通过，说明当前用户已登录，将解析的用户ID存入到请求头
        String userInfo = userId.toString();
        exchange.mutate().request(builder -> builder.header("user-info",userInfo)).build();
        // 放行
        return chain.filter(exchange);
    }

    private boolean isAllowPath(String path){
        // 1.不需要检验的地址
        List<String> excludePaths = authProperties.getExcludePaths();
        // 2、要放行的路径
        for (String excludePath : excludePaths) {
            //  match(规则，路径)
            if(antPathMatcher.match(excludePath, path)){
                return true;
            }
        }
        return false;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
